package com.gitee.wsl.platform

import java.nio.file.FileSystems


actual val platform: Platform
    get() = JVMPlatform


object JVMPlatform:Platform{

    override val lineSeparator: String
        get() = System.lineSeparator()

    override val fileSeparator: String
        get() = FileSystems.getDefault().separator
    
    override val current: PlatformType
        get(){
            val os = System.getProperty("os.name").lowercase()
            return if (os.startsWith("mac os x")) {
                MacosPlatform.current
            } else if (os.startsWith("windows")) {
                WindowPlatform.current
            } else {
                LinuxPlatform.current
            }
        }

    override fun readEnvironmentVariable(key: String): String? {
        return System.getProperty(key)
    }

    override fun onShutdown(dispose: () -> Unit) {
        Runtime.getRuntime().addShutdownHook(Thread { dispose() })
    }


    /** Registers the given [thread] as a new virtual-machine shutdown hook. */
     fun addShutDownHook(thread: Thread): Unit = Runtime.getRuntime().addShutdownHook(thread)

    /** Unregisters the given [thread] from the virtual-machine shutdown hooks. */
     fun removeShutdownHook(thread: Thread): Any =
        runCatching { Runtime.getRuntime().removeShutdownHook(thread) }.onFailure {
            if (!it.ignore) throw it else Unit
        }

    val cpuArchitecture: String? = System.getProperty("osArch")

    val osName = System.getProperty("os.name") ?: "Unknown" // what about "java.vm.vendor" or "java.vendor" (both "Arch Linux" on my machine)

    val osVersion = System.getProperty("os.version") ?: "Unknown"


    val userName = System.getProperty("user.name")

    val userLanguage = System.getProperty("user.language")

    val userCountry = System.getProperty("user.country")

    val userVariant = System.getProperty("user.variant")

    val userTimeZone = System.getProperty("user.timezone")


    val userHome = System.getProperty("user.home")

    val currentDir = System.getProperty("user.dir") // TODO: or convert to method to reflect always current state?

    val tmpDir = System.getProperty("java.io.tmpdir")


    val isRunningTestsWithGradle = System.getProperty("org.gradle.test.worker") != null


    internal fun printStderr(message: String, newline: Boolean) {
        if (newline) {
            System.err.println(message)
        } else {
            System.err.print(message)
        }
    }

    internal  fun readLineOrNullMpp(hideInput: Boolean): String? {
        if (hideInput) {
            val console = System.console()
            if (console != null) {
                return console.readPassword().concatToString()
            }
        }
        return readlnOrNull()
    }

    val appName: String? by lazy {
        try {
            val jarPath = JVMPlatform::class.java.protectionDomain
                ?.codeSource
                ?.location
                ?.toURI()
                ?.path

            jarPath?.split('/')?.last { it.isNotBlank() }
        } catch (e: Throwable) { // TODO: log to error logger
            println { "Could not get app name from jar name (is a security manager installed?)" }

            null
        }
    }


}

private val Throwable.ignore: Boolean
    get() = this::class.simpleName?.let { it == "AccessControlException" || it == "IllegalStateException" } ?: false


//private fun hostOs(name: String) = name.lowercase().let { osName ->
//    when {
//        osName.startsWith("mac") ||
//                osName.startsWith("osx") ||
//                osName.startsWith("darwin") -> DesktopOs.Macos
//
//        osName.startsWith("win") -> DesktopOs.Windows
//        osName.startsWith("linux") -> DesktopOs.Linux
//        else -> DesktopOs.Unknown
//    }
//}
//
//internal fun hostOs(osName: String, archName: String, version: String): Platform.OS {
//    val arch = hostArch(archName)
//    return when (hostOs(osName)) {
//        DesktopOs.Macos -> Platform.OS.MacOs(arch, version)
//        DesktopOs.Linux -> Platform.OS.Linux(arch, version)
//        DesktopOs.Windows -> Platform.OS.Windows(arch, version)
//        DesktopOs.Unknown -> Platform.OS.Unknown(arch, version)
//    }
//}


/**
 * The context ClassLoader for the current [Thread].
 *
 * The context [ClassLoader] is provided by the creator of the [Thread] for use
 * by code running in this thread when loading classes and resources.
 */
// val contextClassLoader: ClassLoader
//    get() = Thread.currentThread().contextClassLoader
//
//private val jvmArgs: List<String>
//    get() {
//        val classLoader = contextClassLoader
//        return classLoader.loadClassOrNull("java.lang.management.ManagementFactory")?.let {
//            val runtimeMxBean: Any = it.getMethod("getRuntimeMXBean").invoke(null)
//            val runtimeMxBeanClass: Class<*> = classLoader.loadClass("java.lang.management.RuntimeMXBean")
//            val inputArgs: Any = runtimeMxBeanClass.getMethod("getInputArguments").invoke(runtimeMxBean)
//            (inputArgs as? List<*>)?.map { arg -> arg.toString() }
//        } ?: emptyList()
//    }
//
//private val jvmJavaAgents: List<String>
//    get() = jvmArgs.filter { it.startsWith("-javaagent") }
//
//private val intellijTraits: List<String>
//    get() = listOf("jetbrains", "intellij", "idea", "idea_rt.jar")
//
///** Whether this program is started by [IDEA IntelliJ](https://www.jetbrains.com/lp/intellij-frameworks/). */
// val isIntelliJ: Boolean
//    get() = runCatching { jvmJavaAgents.any { it.containsAny(intellijTraits, ignoreCase = true) } }.getOrElse { false }
//
///** Whether this program is running in debug mode. */
//@Suppress("SpellCheckingInspection")
// actual val isDebugging: Boolean
//    get() = jvmArgs.any { it.startsWith("-agentlib:jdwp") || it.startsWith("-Xrunjdwp") } || jvmJavaAgents.any { it.contains("debugger") }

